package com.cmii.sjw.department.control.jsc.service.impl;
import cn.dev33.satoken.stp.StpUtil;
import cn.hutool.core.lang.Pair;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.cmii.sjw.department.control.common.RedisService;
import com.cmii.sjw.department.control.jsc.exception.BaseException;
import com.cmii.sjw.department.control.jsc.mapper.*;
import com.cmii.sjw.department.control.jsc.model.User;
import com.cmii.sjw.department.control.jsc.model.dto.*;
import com.cmii.sjw.department.control.jsc.model.entity.*;
import com.cmii.sjw.department.control.jsc.model.vo.ApprovalApplicationVo;
import com.cmii.sjw.department.control.jsc.model.vo.HomePageVo;
import com.cmii.sjw.department.control.jsc.model.vo.StatsSnapshotVo;
import com.cmii.sjw.department.control.jsc.service.CockpitMetricsTreeService;
import com.cmii.sjw.department.control.jsc.util.Result;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.util.ObjectUtils;

import java.time.LocalDateTime;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * @author: jfh
 * @date: 2025-04-22 周二 15:49
 * @version: 1.0
 * @description: 驾驶舱指标信息树
 */
@Slf4j
@Service
 public class CockpitMetricsTreeServiceImpl implements CockpitMetricsTreeService {

    @Autowired
    private CockpitMetricsTreeMapper cockpitMetricsTreeMapper;

    @Autowired
    private GjxxxdhzltxDetailMapper gjxxxdhzltxDetailMapper;

    @Autowired
    private ApprovalChangeLogMapper approvalChangeLogMapper;

    @Autowired
    private ApprovalApplicationMapper approvalApplicationMapper;

    @Autowired
    private UserMapper userMapper;

    @Autowired
    private RedisService redisService;

    @Autowired
    private UserRoleMapper userRoleMapper;

    @Autowired
    private RoleMapper roleMapper;
    @Autowired
    private MetricPermissionService permissionService;


    /**
     * 分页查询指标列表
     * @param query 查询条件
     * @return 指标列表
     */
    @Override
    public Page<MetricsTreeDTO> getNodePage(MetricsTreeNodeQueryDTO query) {

        if (ObjectUtils.isEmpty(query.getId())) {
            throw new BaseException("节点ID不能为空");
        }
        // 1. 获取当前节点及其所有子孙节点ID
//        Set<Long> nodeIds = getAllChildNodeIds(query.getId());
//        nodeIds.add(query.getId()); // 包含当前节点

        Set<Long> allowedMetricIds = permissionService.getUserMetricIds(StpUtil.getLoginIdAsLong());

        if (CollectionUtils.isEmpty(allowedMetricIds)) {
            return new Page<>();
        }

        // 2. 构建查询条件
        QueryWrapper<CockpitMetricsTree> wrapper = new QueryWrapper<>();
//        wrapper.in("id", nodeIds);
        wrapper.and(w -> w.eq("id", query.getId()).or().eq("parent_id", query.getId()))
                .in(!allowedMetricIds.isEmpty(), "id", allowedMetricIds); // 添加权限过滤

        // 3. 精确查询
        wrapper.eq(StringUtils.isNotBlank(query.getStatus()), "status", query.getStatus());
        wrapper.eq(StringUtils.isNotBlank(query.getIsAlertIndicator()),"is_alert_indicator",query.getIsAlertIndicator());

        // 4. 模糊查询
        wrapper.like(StringUtils.isNotBlank(query.getLabel()), "indicator", query.getLabel());

        // 5. 时间范围查询
        if ( query.getStartUpdated() != null && query.getEndUpdated() != null) {
            wrapper.between("updated_at", query.getStartUpdated(), query.getEndUpdated());
        }

        // 6. 添加排序
        if (StringUtils.isNotBlank(query.getSortField())) {
            wrapper.orderBy(true, "asc".equalsIgnoreCase(query.getSortOrder()),
                    query.getSortField());
        }

        // 7. 执行分页查询
        Page<CockpitMetricsTree> page = new Page<>(query.getPageNum(), query.getPageSize());
        Page<CockpitMetricsTree> resultPage = cockpitMetricsTreeMapper.selectPage(page, wrapper);

        return (Page<MetricsTreeDTO>) resultPage.convert(this::convertToMetricsTreeDTO);
    }

    /**
     * 保存为草稿
     * @param drafts 草稿信息
     */
    @Override
    public void saveAsDraft(List<ApprovalChangeLog> drafts) {
        drafts.forEach(this::handleChangeLog);
    }

    @Transactional(rollbackFor = Exception.class)
    public void handleChangeLog(ApprovalChangeLog changeLog) {

        if (StringUtils.isBlank(changeLog.getNewValue())) {
            throw new BaseException(changeLog.getFieldName()+"不能为空");
        }

        long userId = StpUtil.getLoginIdAsLong();
        if (changeLog.getId() == null || "".equals(changeLog.getId())) {

            long metricId = changeLog.getMetricId();
            CockpitMetricsTree metric = cockpitMetricsTreeMapper.selectById(metricId);

            if (metric.getStatus().equals("2")){
                throw new BaseException("指标处于审批中，请勿修改");
            }

            ApprovalChangeLog saveLog = new ApprovalChangeLog();
            //复制属性
            BeanUtils.copyProperties(changeLog,saveLog);
            saveLog.setStatus("1");
            saveLog.setCreatedBy(userId);
            approvalChangeLogMapper.insert(saveLog);

            // 更新指标状态为1
            cockpitMetricsTreeMapper.update(
                    new CockpitMetricsTree()
                            .setStatus("1")
                            .setUpdatedBy(userId),
                    Wrappers.<CockpitMetricsTree>lambdaUpdate()
                            .eq(CockpitMetricsTree::getId, metricId)
            );
        } else {
            // 添加存在性校验
            Long id = changeLog.getId();
            if (approvalChangeLogMapper.selectById(id) != null) {
                int affectedRows = approvalChangeLogMapper.update(
                        new ApprovalChangeLog()
                                .setFieldName(changeLog.getFieldName())
                                .setNewValue(changeLog.getNewValue())
                                .setUpdatedBy(userId),
                        Wrappers.<ApprovalChangeLog>lambdaUpdate()
                                .eq(ApprovalChangeLog::getId, id)
                                .eq(ApprovalChangeLog::getStatus, "1")
                );

                if (affectedRows == 0) {
                    throw new BaseException("无法更新记录，可能记录不存在或状态不为1");
                }
            } else {
                throw new BaseException("指标记录异常，id: " + id);
            }
        }
    }

    /**
     * 获取当前节点及其所有子节点ID
     * @param parentId 父节点ID
     * @return 子节点ID集合
     */
    private Set<Long> getAllChildNodeIds(Long parentId) {
        Set<Long> allChildIds = new HashSet<>();
        Queue<Long> queue = new LinkedList<>();
        queue.offer(parentId);

        while (!queue.isEmpty()) {
            Long currentId = queue.poll();
            // 查询直接子节点
            List<CockpitMetricsTree> children = cockpitMetricsTreeMapper.selectList(
                    new QueryWrapper<CockpitMetricsTree>().eq("parent_id", currentId)
            );

            // 将子节点ID加入结果集并继续查询
            children.forEach(child -> {
                if (!allChildIds.contains(child.getId())) {
                    allChildIds.add(child.getId());
                    queue.offer(child.getId());
                }
            });
        }
        return allChildIds;
    }

    /**
     * 获取指标信息树
     * @return 指标信息树
     */
    @Override
    public List<MetricsTreeNodeDTO> getMetricsTree() {

        // 1. 尝试从缓存获取
        String cacheKey = "metrics:tree:full";
        List<MetricsTreeNodeDTO> cachedResult = (List<MetricsTreeNodeDTO>) redisService.getCollection(cacheKey, MetricsTreeNodeDTO.class);
        if (!cachedResult.isEmpty()) {
            log.info("从缓存获取指标树");
            return cachedResult;
        }

        // 2. 获取当前用户允许访问的指标ID
        Set<Long> allowedMetricIds = permissionService.getUserMetricIds(StpUtil.getLoginIdAsLong());
        // 查询所有节点数据
        List<CockpitMetricsTree> allNodes = allowedMetricIds.isEmpty() ?
                Collections.emptyList() :
                cockpitMetricsTreeMapper.selectList(new QueryWrapper<CockpitMetricsTree>()
                        .in("id", allowedMetricIds));

        List<MetricsTreeNodeDTO> result = buildTreeMax(allNodes);
        // 3. 写入缓存(设置30分钟过期)
        redisService.setCache(cacheKey, result, 1800 );
        return result;
    }

    private List<MetricsTreeNodeDTO> buildTreeMax(List<CockpitMetricsTree> nodes) {
        Map<Long, MetricsTreeNodeDTO> nodeMap = new HashMap<>();
        Map<Long, List<MetricsTreeNodeDTO>> levelMap = new HashMap<>();

        // 构建节点映射和层级映射
        for (CockpitMetricsTree node : nodes) {
            MetricsTreeNodeDTO dto = convertToDTO(node);
            nodeMap.put(node.getId(), dto);
            levelMap.computeIfAbsent(node.getParentId(), k -> new ArrayList<>()).add(dto);
        }

        // 从根节点(父ID为null或0)开始构建树
        List<MetricsTreeNodeDTO> rootNodes = levelMap.getOrDefault(0L, levelMap.getOrDefault(null, new ArrayList<>()));

        // 使用栈来迭代构建子树
        Deque<MetricsTreeNodeDTO> stack = new ArrayDeque<>(rootNodes);
        while (!stack.isEmpty()) {
            MetricsTreeNodeDTO parentNode = stack.pop();
            List<MetricsTreeNodeDTO> children = levelMap.get(parentNode.getId());
            if (children != null && !children.isEmpty()) {
                parentNode.setChildren(children);
                stack.addAll(children);
            }
        }

        return rootNodes;
    }


    /**
     * 获取指定层级的指标信息树
     * @param levels 层级数
     * @return 指定层级的指标信息树
     */
    @Override
    public List<MetricsTreeNodeDTO> getTreeWithLevels(int levels) {
        Set<Long> allowedMetricIds = permissionService.getUserMetricIds(StpUtil.getLoginIdAsLong());

        // 只加载指定层级的节点
        List<CockpitMetricsTree> nodes = allowedMetricIds.isEmpty() ?
                Collections.emptyList() :
                cockpitMetricsTreeMapper.selectList(new QueryWrapper<CockpitMetricsTree>()
                        .in("id", allowedMetricIds)
                        .le("level", levels));
        return buildTree(nodes);
    }

    /**
     * 获取指定父节点的直接子节点
     * @param parentId 父节点ID
     * @return 指定父节点的直接子节点
     */
    @Override
    public List<MetricsTreeNodeDTO> getNodeLoading(Long parentId) {
        // 只查询指定父节点下的直接子节点
        List<CockpitMetricsTree> nodes = cockpitMetricsTreeMapper.selectList(
                new QueryWrapper<CockpitMetricsTree>()
                        .eq(parentId != null, "parent_id", parentId)
                        .isNull(parentId == null, "parent_id")
        );
        return nodes.stream().map(this::convertToDTO).collect(Collectors.toList());
    }

    /**
     * 构建树形结构
     * @param nodes 节点列表
     * @return 树形结构数据
     */
    private List<MetricsTreeNodeDTO> buildTree(List<CockpitMetricsTree> nodes) {
        // 按层级分组
        Map<Long, List<MetricsTreeNodeDTO>> levelMap = nodes.stream() //parallelStream()
                .collect(Collectors.groupingBy(
                        CockpitMetricsTree::getParentId,
                        Collectors.mapping(this::convertToDTO, Collectors.toList())
                ));

        // 从根节点(父ID为null或0)开始构建树
        List<MetricsTreeNodeDTO> rootNodes = levelMap.getOrDefault(0L, new ArrayList<>());
        if (rootNodes.isEmpty()) {
            rootNodes = levelMap.getOrDefault(null, new ArrayList<>());
        }

        // 递归构建子树
        rootNodes.forEach(node -> buildChildren(node, levelMap));
        return rootNodes;
    }

    /**
     * 递归构建子树
     * @param parentNode 父节点
     * @param levelMap 层级映射
     */
    private void buildChildren(MetricsTreeNodeDTO parentNode, Map<Long, List<MetricsTreeNodeDTO>> levelMap) {
        Long id = parentNode.getId();
        List<MetricsTreeNodeDTO> children = levelMap.getOrDefault(id, new ArrayList<>());
        if (!children.isEmpty()) {
            parentNode.setChildren(children);
            children.forEach(child -> buildChildren(child, levelMap));
        }
    }

    /**
     * 将实体转换为DTO
     * @param node 实体
     * @return DTO
     */
    private MetricsTreeNodeDTO  convertToDTO(CockpitMetricsTree node) {
        MetricsTreeNodeDTO dto = new MetricsTreeNodeDTO();
        dto.setId(node.getId());
        dto.setLevel(node.getLevel());
        dto.setLabel(node.getIndicator());
        dto.setBusinessType(node.getBusinessType());
        dto.setIndicatorType(node.getIndicatorType());
        dto.setCurrentValue(node.getCurrentValue());
        dto.setTargetValue(node.getTargetValue());
        dto.setUnit(node.getUnit());
        dto.setIsAlertIndicator(node.getIsAlertIndicator());
        return dto;
    }
    /**
     * 将实体转换为DTO
     * @param node 实体
     * @return DTO
     */
    private MetricsTreeDTO  convertToMetricsTreeDTO(CockpitMetricsTree node) {
        MetricsTreeDTO dto = new MetricsTreeDTO();
        //复制属性
        BeanUtils.copyProperties(node,dto);
        //1保存 2提交审批
        if ("1".equals(node.getStatus()) || "2".equals(node.getStatus())) {
            List<ApprovalChangeLog> changeLogs = approvalChangeLogMapper.selectList(
                    new QueryWrapper<ApprovalChangeLog>()
                            .eq("metric_id", node.getId())
                            .eq("status", node.getStatus())
            );
            changeLogs.forEach(changeLog -> {
                switch (changeLog.getFieldName()) {
                    case "指标名称":
                        dto.setNewIndicator(changeLog.getNewValue());
                        dto.setNewIndicatorId(changeLog.getId());
                        break;
                    case "指标修改":
                        dto.setNewCurrentValue(changeLog.getNewValue());
                        dto.setNewCurrentValueId(changeLog.getId());
                        break;
                    case "目标修改":
                        dto.setNewTargetValue(changeLog.getNewValue());
                        dto.setNewTargetValueId(changeLog.getId());
                        break;
                    case "预警指标":
                        dto.setNewIsAlertIndicator(changeLog.getNewValue());
                        dto.setNewIsAlertIndicatorId(changeLog.getId());
                        break;
                    case "数据源":
                        dto.setNewDataType(changeLog.getNewValue());
                        dto.setNewDataTypeId(changeLog.getId());
                        break;
                    default:
                        // 可选：处理未知字段或记录日志
                        break;
                }
            });
        }
        return dto;
    }

    @Override
    public void buildIndicatorTree() {

//        List<CockpitQhjsdwjsDetail> sourceData = qhjsdwjsMapper.selectList(new QueryWrapper<>());
//        List<CockpitPysdxrDetail> sourceData = pysdxrDetailMapper.selectList(new QueryWrapper<>());
//        List<CockpitJsgzljytxDetail> sourceData = jsgzljytxDetailMapper.selectList(new QueryWrapper<>());
//        List<CockpitFwjjshfzDetail> sourceData = fwjjshfzDetailMapper.selectList(new QueryWrapper<>());
        List<CockpitGjxxxdhzltxDetail> sourceData = gjxxxdhzltxDetailMapper.selectList(new QueryWrapper<>());
        log.info("开始迁移数据，共查询到{}条源数据", sourceData.size());
        migrateDataToMetricsTree(sourceData);
    }

    /**
     * 将源数据迁移到目标表
     * @param sourceData 源数据列表
     */
    @Transactional
    public void migrateDataToMetricsTree(List<CockpitGjxxxdhzltxDetail> sourceData) {

        // 使用Map记录各层级节点ID
        Map<String, Long> sectionMap = new HashMap<>();
        Map<String, Long> subsectionMap = new HashMap<>();
        Map<String, Long> indicatorMap = new HashMap<>();
        Map<String, Long> level1Map = new HashMap<>();
        Map<String, Long> level2Map = new HashMap<>();
        Map<String, Long> level3Map = new HashMap<>();
        Map<String, Long> level4Map = new HashMap<>();

        // 1. 处理板块节点
        sourceData.stream()
                .map(CockpitGjxxxdhzltxDetail::getSection)
                .distinct()
                .forEach(section -> {
                    CockpitMetricsTree node = createNode("体征指标", "板块", section, 1L,1);
                    cockpitMetricsTreeMapper.insert(node);
                    sectionMap.put(section, node.getId());
                });

        // 2. 处理子版块节点
        sourceData.stream()
                .filter(item -> item.getSubsection() != null)
                .map(item -> new Pair<>(item.getSection(), item.getSubsection()))
                .distinct()
                .forEach(pair -> {
                    CockpitMetricsTree node = createNode("体征指标", "子版块", pair.getValue(), sectionMap.get(pair.getKey()),2);
                    cockpitMetricsTreeMapper.insert(node);
                    subsectionMap.put(pair.getValue(), node.getId());
                });

        // 3. 处理核心指标节点
        sourceData.stream()
                .filter(item -> item.getIndicator() != null)
                .map(item -> new Pair<>(item.getSubsection(), item.getIndicator()))
                .distinct()
                .forEach(pair -> {

                    CockpitMetricsTree node = createNode("体征指标", "指标", pair.getValue(), subsectionMap.get(pair.getKey()), 3);
                    cockpitMetricsTreeMapper.insert(node);
                    indicatorMap.put(pair.getValue(), node.getId());
                });

        // 4. 处理level1指标节点
        sourceData.stream()
                .filter(item -> item.getLevel1Indicator() != null)
                .map(item -> new Pair<>(item.getIndicator(), item.getLevel1Indicator()))
                .distinct()
                .forEach(pair -> {
                    CockpitMetricsTree node = createNode("体征指标", "指标", pair.getValue(), indicatorMap.get(pair.getKey()),4);
                    cockpitMetricsTreeMapper.insert(node);
                    level1Map.put(pair.getValue(), node.getId());
                });

        // 5. 处理level2指标节点
        sourceData.stream()
                .filter(item -> item.getLevel2Indicator() != null)
                .map(item -> new Pair<>(item.getLevel1Indicator(), item.getLevel2Indicator()))
                .distinct()
                .forEach(pair -> {
                    CockpitMetricsTree node = createNode("体征指标", "指标", pair.getValue(), level1Map.get(pair.getKey()),5);
                    cockpitMetricsTreeMapper.insert(node);
                    level2Map.put(pair.getValue(), node.getId());
                });

        // 6. 处理level3指标节点
        sourceData.stream()
                .filter(item -> item.getLevel3Indicator() != null)
                .map(item -> new Pair<>(item.getLevel2Indicator(), item.getLevel3Indicator()))
                .distinct()
                .forEach(pair -> {
                    CockpitMetricsTree node = createNode("体征指标", "指标", pair.getValue(), level2Map.get(pair.getKey()),6);
                    cockpitMetricsTreeMapper.insert(node);
                    node.setCurrentValue(pair.getValue());
                    level3Map.put(pair.getValue(), node.getId());
                });
        // 7. 处理level4指标节点
        sourceData.stream()
                .filter(item -> item.getLevel4Indicator() != null)
                .map(item -> new Pair<>(item.getLevel3Indicator(), item.getLevel4Indicator()))
                .distinct()
                .forEach(pair -> {
                    CockpitMetricsTree node = createNode("体征指标", "指标", pair.getValue(), level3Map.get(pair.getKey()),7);
                    cockpitMetricsTreeMapper.insert(node);
                    node.setCurrentValue(pair.getValue());
                    level4Map.put(pair.getValue(), node.getId());
                });

        log.info("数据迁移完成，共迁移{}条数据", sourceData.size());
    }

    private CockpitMetricsTree createNode(String businessType, String indicatorType, String name, Long parentId,Integer level) {
        CockpitMetricsTree node = new CockpitMetricsTree();
        node.setBusinessType(businessType);
        node.setIndicatorType(indicatorType);
        node.setIndicator(name);
        node.setParentId(parentId);
        node.setLevel(level);
        return node;
    }

    /**
     * 获取指标历史记录
     * @param id 指
     * @return 指标历史记录
     */
    @Override
    public Result<List<HistoricalRecordsDTO>> getHistoricalRecords(Long id) {
        List<HistoricalRecordsDTO> historicalRecords = new ArrayList<>();
        try {
            List<ApprovalChangeLog> approvalChangeLogs =  approvalChangeLogMapper.selectList(
                    new LambdaQueryWrapper<ApprovalChangeLog>()
                            .eq(ApprovalChangeLog::getMetricId, id)
                            .orderByDesc(ApprovalChangeLog::getCreatedAt)
            );
            approvalChangeLogs.forEach( approval -> {
                HistoricalRecordsDTO historicalRecord = new HistoricalRecordsDTO();
                historicalRecord.setFieldName(approval.getFieldName());
                historicalRecord.setNewValue(approval.getNewValue());
                if(approval.getApplicationId() != null){
                    ApprovalApplication application = approvalApplicationMapper.selectById(approval.getApplicationId());
                    historicalRecord.setStatus(application.getStatus());
                    if (application.getApprover() != null) {
                        User user = userMapper.selectById(application.getApprover());
                        historicalRecord.setApprover(user.getNickName());
                        historicalRecord.setApprovedAt(application.getCreatedAt());
                    }

                }
                historicalRecords.add(historicalRecord);
            });

        }   catch (Exception e) {
            log.error("获取指标历史记录失败", e);
            return Result.error("获取指标历史记录失败");
        }
        return Result.success(historicalRecords);
    }

    /**
     * 指标申请单
     * @param ids 指标ID
     * @return Result
     */
    @Override
    public MetricsAppFormDTO metricApply(Long[] ids) {
        // 参数有效性校验
        if (ids == null || ids.length == 0) {
            throw new BaseException("报批指标ID列表不能为空");
        }
        // 查询指标数据
        List<Long> idList = Arrays.asList(ids);
        List<CockpitMetricsTree> cockpitMetricsTreeList = cockpitMetricsTreeMapper.selectBatchIds(idList);
        // 批量状态校验
        List<String> invalidIndicators = cockpitMetricsTreeList.stream()
                .filter(item -> !"1".equals(item.getStatus()))
                .map(CockpitMetricsTree::getIndicator)
                .collect(Collectors.toList());

        if (!invalidIndicators.isEmpty()) {
            String errorMsg = String.format("以下指标无需报批：%s", String.join("、", invalidIndicators));
            throw new BaseException(errorMsg);
        }

        long userId = StpUtil.getLoginIdAsLong();
        User user = userMapper.selectById(userId);

        MetricsAppFormDTO metricsAppFormDTO = new MetricsAppFormDTO();
        List<ApprovalChangeLog> approvalChangeLogs =  approvalChangeLogMapper.selectList(
                new LambdaQueryWrapper<ApprovalChangeLog>()
                        .in(ApprovalChangeLog::getMetricId, ids)
                        .eq(ApprovalChangeLog::getStatus, "1")
                        .orderByDesc(ApprovalChangeLog::getCreatedAt)
        );
        if(approvalChangeLogs.isEmpty()){
            throw new BaseException("选中指标无报批信息");
        }
        //  生成申请单号
        metricsAppFormDTO.setApplicationNo(redisService.orderNoGenerator("AP"));
        // 报批人
        metricsAppFormDTO.setApplicant(user.getNickName());
        // 报批时间
        metricsAppFormDTO.setCreatedAt(LocalDateTime.now());
        // 数量
        metricsAppFormDTO.setQuantity(approvalChangeLogs.size());
        // 报批明细
        metricsAppFormDTO.setDetailed(approvalChangeLogs);

        return metricsAppFormDTO;
    }

    /**
     * 提交申请单
     * @param metricsAppFormDTO 申请单信息
     * @return Result
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Result<String> submitApply(MetricsAppFormDTO metricsAppFormDTO) {
        try {
            Long count = approvalApplicationMapper.selectCount(
                    new LambdaQueryWrapper<ApprovalApplication>()
                           .eq(ApprovalApplication::getApplicationNo, metricsAppFormDTO.getApplicationNo())
            );
            if(count > 0){
                return Result.error("该申请单已报批");
            }

            long userId = StpUtil.getLoginIdAsLong();

            ApprovalApplication saveApplication = new ApprovalApplication()
                    .setApplicationNo(metricsAppFormDTO.getApplicationNo())
                    .setQuantity(metricsAppFormDTO.getQuantity())
                    .setReason(metricsAppFormDTO.getReason())
                    .setApplicant(userId)
                    .setStatus("2")
                    .setCreatedAt(metricsAppFormDTO.getCreatedAt())
                    .setCreatedBy(userId);

            if (approvalApplicationMapper.insert(saveApplication) <= 0) {
                throw new BaseException("报批申请信息表保存失败");
            }

            // 批量更新日志
            List<Long> itemIds = metricsAppFormDTO.getDetailed().stream()
                    .map(ApprovalChangeLog::getId)
                    .filter(Objects::nonNull)
                    .collect(Collectors.toList());

            if (!itemIds.isEmpty()) {

                //需要判断审批变更日志的状态是否为1
                List<ApprovalChangeLog> approvalChangeLogs = approvalChangeLogMapper.selectList(
                        new LambdaQueryWrapper<ApprovalChangeLog>()
                              .in(ApprovalChangeLog::getId, itemIds)
                );
                if(approvalChangeLogs.stream().anyMatch(item -> !"1".equals(item.getStatus()))){
                    throw new BaseException("报批申请指标状态已经变更");
                }

                approvalChangeLogMapper.update(
                        new ApprovalChangeLog()
                                .setStatus("2")
                                .setUpdatedBy(userId)
                                .setApplicationId(saveApplication.getId()),
                        new LambdaUpdateWrapper<ApprovalChangeLog>()
                                .in(ApprovalChangeLog::getId, itemIds)
                );
            }

            // 指标更新
            List<Long> metricIds = metricsAppFormDTO.getDetailed().stream()
                    .map(ApprovalChangeLog::getMetricId)
                    .filter(Objects::nonNull)
                    .distinct()
                    .collect(Collectors.toList());

            //需要判断驾驶舱指标树的状态是否为1
            List<CockpitMetricsTree> cockpitMetricsTreeList = cockpitMetricsTreeMapper.selectList(
                    new LambdaQueryWrapper<CockpitMetricsTree>()
                            .in(CockpitMetricsTree::getId, metricIds)
            );
            if(cockpitMetricsTreeList.stream().anyMatch(item -> !"1".equals(item.getStatus()))){
                throw new BaseException("报批申请指标状态已经变更");
            }

            if (!metricIds.isEmpty()) {
                cockpitMetricsTreeMapper.update(
                        new CockpitMetricsTree().setStatus("2"),
                        new LambdaQueryWrapper<CockpitMetricsTree>()
                                .in(CockpitMetricsTree::getId, metricIds)
                );
            }

        } catch (Exception e) {
            log.error("提交申请单失败", e);
            return Result.error("提交申请单失败");
        }
        return Result.success("提交申请单成功");
    }

    /**
     * 申请历史分页
     * @param applyHistoryDTO 包含分页参数和查询条件的DTO
     * @return 分页的审批申请历史记录
     */
    @Override
    public Result<Page<ApprovalApplication>> applyHistoryPage(ApplyHistoryDTO applyHistoryDTO) {
        // 获取当前登录用户的ID
        Long userId = StpUtil.getLoginIdAsLong();
        return Result.success(historyPage(applyHistoryDTO, userId));
    }

    /**
     * 申请历史分页
     * @param applyHistoryDTO 包含分页参数和查询条件的DTO
     * @return 分页的审批申请历史记录
     */
    public Page<ApprovalApplication> historyPage(ApplyHistoryDTO applyHistoryDTO,Long userId) {
        // 构建分页对象
        Page<ApprovalApplication> page = new Page<>(applyHistoryDTO.getPageNum(), applyHistoryDTO.getPageSize());

        // 构建查询条件
        LambdaQueryWrapper<ApprovalApplication> wrapper = new LambdaQueryWrapper<>();
        if (!ObjectUtils.isEmpty(userId)){
            wrapper.eq(ApprovalApplication::getApplicant, userId);
        }

        // 添加申请人名称模糊查询条件
        if (StringUtils.isNotEmpty(applyHistoryDTO.getApplicantName())){
            Set<Long> userIds = userMapper.selectList(
                    new LambdaQueryWrapper<User>()
                            .like(User::getNickName, applyHistoryDTO.getApplicantName())
            ).stream().map(User::getUserId).collect(Collectors.toSet());
            if (userIds.isEmpty()){
                return new Page<>();
            }
            wrapper.in(ApprovalApplication::getApplicant, userIds);
        }
        // 添加申请单号模糊查询条件
        if (StringUtils.isNotBlank(applyHistoryDTO.getApplicationNo())) {
            wrapper.like(ApprovalApplication::getApplicationNo, applyHistoryDTO.getApplicationNo());
        }

        // 添加状态查询条件
        if (StringUtils.isNotBlank(applyHistoryDTO.getStatus())) {
            wrapper.eq(ApprovalApplication::getStatus, applyHistoryDTO.getStatus());
        }else if (ObjectUtils.isEmpty(userId)){
            wrapper.in(ApprovalApplication::getStatus, Arrays.asList("0", "2", "3"));
        }

        // 添加时间范围查询条件
        if (applyHistoryDTO.getStartDated() != null && applyHistoryDTO.getEndDated() != null) {
            wrapper.between(ApprovalApplication::getCreatedAt,
                    applyHistoryDTO.getStartDated(),
                    applyHistoryDTO.getEndDated());
        }
        wrapper.orderByDesc(ApprovalApplication::getCreatedAt);

        // 执行分页查询
        return approvalApplicationMapper.selectPage(page, wrapper);
    }

    /**
     * 申请历史详情
     * @param id 申请ID
     * @return Result 审批历史详情
     */
    @Override
    public Result<MetricsAppFormDTO> applyHistoryDetails(Long id) {
        // 参数校验前置
        if (id == null || id <= 0L) {
            return Result.error("非法申请ID");
        }

        // 使用 Optional 处理可能为空的情况
        ApprovalApplication approvalApplication = Optional.ofNullable(
                        approvalApplicationMapper.selectOne(
                                new LambdaQueryWrapper<ApprovalApplication>()
                                        .eq(ApprovalApplication::getId, id)
                        ))
                .orElseThrow(() -> new BaseException("申请记录不存在"));

        MetricsAppFormDTO metricsAppFormDTO = new MetricsAppFormDTO();

        // 使用 BeanUtils 进行属性拷贝（需确保字段名称一致）
        BeanUtils.copyProperties(approvalApplication, metricsAppFormDTO);

        // 用户信息查询优化
        Set<Long> userIds = new HashSet<>();
        if (approvalApplication.getApprover() != null) {
            userIds.add(approvalApplication.getApprover());
        }
        userIds.add(approvalApplication.getApplicant());

        Map<Long, User> userMap = userMapper.selectBatchIds(userIds)
                .stream()
                .collect(Collectors.toMap(User::getUserId, Function.identity()));

        // 申请人信息设置
        User applicant = userMap.get(approvalApplication.getApplicant());
        metricsAppFormDTO.setApplicant(applicant != null ? applicant.getNickName() : "未知用户");

        // 审批人信息设置
        if (approvalApplication.getApprover() != null) {
            User approver = userMap.get(approvalApplication.getApprover());
            metricsAppFormDTO.setApprover(approver != null ? approver.getNickName() : "未知审批人");
            metricsAppFormDTO.setApprovalComment(approvalApplication.getApprovalComment());
            metricsAppFormDTO.setApprovalAt(approvalApplication.getApprovalAt());
        }

        // 变更记录查询保持原逻辑
        List<ApprovalChangeLog> changeLogs = approvalChangeLogMapper.selectList(
                new LambdaQueryWrapper<ApprovalChangeLog>()
                        .eq(ApprovalChangeLog::getApplicationId, id)
        );
        metricsAppFormDTO.setDetailed(changeLogs);

        return Result.success(metricsAppFormDTO);
    }


    /**
     * 审核
     * @param auditInfoDTO 审核信息
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Result<String> revokeInvalid(AuditInfoDTO auditInfoDTO) {
        long userId = StpUtil.getLoginIdAsLong();
        // 检查审批状态
        ApprovalApplication approvalApplication = approvalApplicationMapper.selectOne(
                new LambdaQueryWrapper<ApprovalApplication>()
                        .eq(ApprovalApplication::getId, auditInfoDTO.getApplicationId())
                        .eq(ApprovalApplication::getApplicationNo, auditInfoDTO.getApplicationNo())
                        .eq(ApprovalApplication::getStatus, "2")
                        .eq(ApprovalApplication::getApplicant, userId)
        );
        if (approvalApplication == null) {
            throw new BaseException("审批状态异常，无法操作！");
        }

        try {

            ApprovalApplication updateAa= new ApprovalApplication()
                    .setStatus(auditInfoDTO.getStatus())
                    .setApprovalAt(LocalDateTime.now())
                    .setUpdatedBy(userId)
                    .setUpdatedAt(LocalDateTime.now());
            if (StringUtils.isNotBlank(auditInfoDTO.getApprovalComment())) {
                updateAa.setApprovalComment(auditInfoDTO.getApprovalComment());
            }
            if (auditInfoDTO.getStatus().equals("3") || auditInfoDTO.getStatus().equals("0")) {
                updateAa.setApprover(userId);
            }
            // 申请单状态变更
            approvalApplicationMapper.update(updateAa,
                    new LambdaUpdateWrapper<ApprovalApplication>()
                            .eq(ApprovalApplication::getId, auditInfoDTO.getApplicationId())
                            .eq(ApprovalApplication::getApplicationNo, auditInfoDTO.getApplicationNo())
            );
            // 变更记录状态变更
            approvalChangeLogMapper.update(
                    new ApprovalChangeLog()
                            .setApplicationId(auditInfoDTO.getApplicationId())
                            .setStatus(auditInfoDTO.getStatus())
                            .setUpdatedBy(userId)
                            .setUpdatedAt(LocalDateTime.now()),
                    new LambdaUpdateWrapper<ApprovalChangeLog>()
                            .eq(ApprovalChangeLog::getApplicationId, auditInfoDTO.getApplicationId())
            );
            // 指标状态
            List<Long> metricIds = approvalChangeLogMapper.selectList(
                    new LambdaQueryWrapper<ApprovalChangeLog>()
                           .eq(ApprovalChangeLog::getApplicationId, auditInfoDTO.getApplicationId())
            ).stream().map(ApprovalChangeLog::getMetricId).distinct().collect(Collectors.toList());

            cockpitMetricsTreeMapper.update(
                    new CockpitMetricsTree().setStatus(auditInfoDTO.getStatus())
                            .setUpdatedBy(userId)
                            .setUpdatedAt(LocalDateTime.now()),
                    new LambdaUpdateWrapper<CockpitMetricsTree>()
                            .in(CockpitMetricsTree::getId, metricIds)

            );

            // 审批通过，更新指标信息
            if (auditInfoDTO.getStatus().equals("3")){
                List<ApprovalChangeLog> changeLogs = approvalChangeLogMapper.selectList(
                        new LambdaQueryWrapper<ApprovalChangeLog>()
                                .eq(ApprovalChangeLog::getApplicationId, auditInfoDTO.getApplicationId())
                );
                // 使用 Map 去重，以 metricId 为键
                Map<Long, CockpitMetricsTree> cockpitMetricsTreeMap = new HashMap<>();
                for (ApprovalChangeLog changeLog : changeLogs) {
                    Long metricId = changeLog.getMetricId();
                    CockpitMetricsTree cockpitMetricsTree = cockpitMetricsTreeMap.computeIfAbsent(metricId, k -> {
                        CockpitMetricsTree tree = new CockpitMetricsTree();
                        tree.setId(metricId);
                        return tree;
                    });

                    // 根据字段名更新指标
                    String fieldName = changeLog.getFieldName().trim().toLowerCase();
                    switch (fieldName) {
                        case "指标名称":
                            cockpitMetricsTree.setIndicator(changeLog.getNewValue());
                            break;
                        case "指标修改":
                            cockpitMetricsTree.setCurrentValue(changeLog.getNewValue());
                            break;
                        case "目标修改":
                            cockpitMetricsTree.setTargetValue(changeLog.getNewValue());
                            break;
                        case "预警指标":
                            cockpitMetricsTree.setIsAlertIndicator(changeLog.getNewValue());
                            break;
                        case "数据源":
                            cockpitMetricsTree.setDataType(changeLog.getNewValue());
                            break;
                    }
                }

                // 批量更新
                if (!cockpitMetricsTreeMap.isEmpty()) {
                    cockpitMetricsTreeMapper.updateBatch(new ArrayList<>(cockpitMetricsTreeMap.values()));
                }

            }

        } catch (Exception e) {
            log.error("审核操作失败，用户ID: {}, 申请ID: {}, 申请编号: {}", userId, auditInfoDTO.getApplicationId(), auditInfoDTO.getApplicationNo(), e);
            throw new BaseException("审核操作失败","400", e);
        }
        return Result.success("审核操作成功");
    }

    /**
     * 审批历史分页
     * @param auditInfoDTO 包含分页参数和查询条件的DTO
     * @return 分页的审批历史记录
     */
    @Override
    public Result<Page<ApprovalApplicationVo>> findAuditsByPage(ApplyHistoryDTO auditInfoDTO) {
        // 执行分页查询
        Page<ApprovalApplication> resultPage = historyPage(auditInfoDTO,null);

        return Result.success((Page<ApprovalApplicationVo>) resultPage.convert(this::convertToApprovalApplicationVo));
    }

    private ApprovalApplicationVo convertToApprovalApplicationVo(ApprovalApplication approvalApplication) {
        long userId = StpUtil.getLoginIdAsLong();
        ApprovalApplicationVo vo = new ApprovalApplicationVo();
        // 复制属性
        BeanUtils.copyProperties(approvalApplication, vo);

        try {
            // 批量查询用户信息
            List<Long> userIds = new ArrayList<>();
            userIds.add(approvalApplication.getApplicant());
            if (!ObjectUtils.isEmpty(approvalApplication.getApprover())) {
                userIds.add(approvalApplication.getApprover());
            }

            Map<Long, User> userMap = userMapper.selectList(new LambdaQueryWrapper<User>().in(User::getUserId, userIds))
                    .stream()
                    .collect(Collectors.toMap(User::getUserId, Function.identity()));

            // 设置申请人姓名
            User applicantUser = userMap.get(approvalApplication.getApplicant());
            if (applicantUser != null) {
                vo.setApplicantName(applicantUser.getNickName());
            }

            // 设置审批人姓名
            if (!ObjectUtils.isEmpty(approvalApplication.getApprover())) {
                User approverUser = userMap.get(approvalApplication.getApprover());
                if (approverUser != null) {
                    vo.setApproverName(approverUser.getNickName());
                }
            }
            if(vo.getCreatedBy().equals(userId)){
                vo.setIsInvalidated("1");
            }else{
                vo.setIsInvalidated("0");
            }

        } catch (Exception e) {
            // 处理异常，记录日志或抛出自定义异常
            throw new BaseException("Failed to convert approval application to vo");
        }

        return vo;
    }

    /**
     * 审批历史分页查询
     * @param query 查询条件
     * @return 分页的审批历史记录
     */
    @Override
    public Page<CockpitMetricsTree> auditsHistory(MetricsTreeNodeQueryDTO query) {

        if (ObjectUtils.isEmpty(query.getId())) {
            throw new BaseException("节点ID不能为空");
        }
        // 1. 获取当前节点及其所有子孙节点ID
//        Set<Long> nodeIds = getAllChildNodeIds(query.getId());
//        nodeIds.add(query.getId()); // 包含当前节点

        // 2. 构建查询条件
        QueryWrapper<CockpitMetricsTree> wrapper = new QueryWrapper<>();
//        wrapper.in("id", nodeIds);
        wrapper.and(w -> w.eq("id", query.getId()).or().eq("parent_id", query.getId()));

        // 3. 精确查询
        wrapper.eq(StringUtils.isNotBlank(query.getStatus()), "status", query.getStatus());
        wrapper.eq(StringUtils.isNotBlank(query.getIsAlertIndicator()),"is_alert_indicator",query.getIsAlertIndicator());

        // 4. 模糊查询
        wrapper.like(StringUtils.isNotBlank(query.getLabel()), "indicator", query.getLabel());

        // 5. 时间范围查询
        if ( query.getStartUpdated() != null && query.getEndUpdated() != null) {
            wrapper.between("updated_at", query.getStartUpdated(), query.getEndUpdated());
        }

        // 6. 添加排序
        if (StringUtils.isNotBlank(query.getSortField())) {
            wrapper.orderBy(true, "asc".equalsIgnoreCase(query.getSortOrder()),
                    query.getSortField());
        }

        // 7. 执行分页查询
        Page<CockpitMetricsTree> page = new Page<>(query.getPageNum(), query.getPageSize());
        return cockpitMetricsTreeMapper.selectPage(page, wrapper);
    }

    /**
     * 首页分页查询
     * @param query 查询条件
     * @return 分页的审批历史记录
     */
    @Override
    public Result<HomePageVo> homePage(HomePageQueryDTO query) {
        HomePageVo homePageVo = new HomePageVo();
        homePageVo.setUserType("ordinary_user");
        // 获取当前登录用户的ID
        Long userId = StpUtil.getLoginIdAsLong();
        try {
            // 获取用户角色并检查是否为 data_audit
            Set<Long> roles = userRoleMapper.selectList(new LambdaQueryWrapper<UserRole>().eq(UserRole::getUserId, userId))
                    .stream().map(UserRole::getRoleId).collect(Collectors.toSet());

            if (!roles.isEmpty()) {
                roleMapper.selectList(new LambdaQueryWrapper<Role>().eq(Role::getStatus, 0).in(Role::getId, roles))
                        .stream()
                        .filter(role -> "data_audit".equals(role.getRoleCode()))
                        .findFirst()
                        .ifPresent(role -> homePageVo.setUserType(role.getRoleCode()));
            }

            log.info("当前用户类型: {}", homePageVo.getUserType());

            // 根据用户类型设置应用页面
            if ("data_audit".equals(homePageVo.getUserType())) {

                Page<ApprovalApplication> resultPage = applicationPage(query, null);
                Page<ApprovalApplicationVo> applicationPage = (Page<ApprovalApplicationVo>) resultPage.convert(this::convertToApprovalApplicationVo);
                homePageVo.setApplicationPage(applicationPage);
            } else {
                Page<ApprovalApplication> resultPage = applicationPage(query, userId);
                Page<ApprovalApplicationVo> applicationPage = (Page<ApprovalApplicationVo>) resultPage.convert(this::convertToApprovalApplicationVo);
                homePageVo.setApplicationPage(applicationPage);
            }

            return Result.success(homePageVo);
        } catch (Exception e) {
            log.error("处理主页数据时发生异常", e);
            return Result.error("处理主页数据时发生异常");
        }
    }

    /**
     * @param query 查询条件
     * @param userId 用户ID
     * @return  分页的审批历史记录
     */
    private Page<ApprovalApplication> applicationPage(HomePageQueryDTO query,Long userId) {
        // 构建分页对象
        Page<ApprovalApplication> page = new Page<>(query.getPageNum(), query.getPageSize());

        // 构建查询条件
        LambdaQueryWrapper<ApprovalApplication> wrapper = new LambdaQueryWrapper<>();
        if (!ObjectUtils.isEmpty(userId)){
            wrapper.eq(ApprovalApplication::getApplicant, userId);
        }

        // 添加申请人名称模糊查询条件
//        if (StringUtils.isNotEmpty(applyHistoryDTO.getApplicantName())){
//            Set<Long> userIds = userMapper.selectList(
//                    new LambdaQueryWrapper<User>()
//                            .like(User::getNickName, applyHistoryDTO.getApplicantName())
//            ).stream().map(User::getUserId).collect(Collectors.toSet());
//            if (userIds.isEmpty()){
//                return new Page<>();
//            }
//            wrapper.in(ApprovalApplication::getApplicant, userIds);
//        }
        // 添加查询条件
        if (StringUtils.isNotBlank(query.getQuery())) {
            wrapper.and(w -> {
                w.like(ApprovalApplication::getApplicationNo, query.getQuery())
                        .or()
                        .like(ApprovalApplication::getReason, query.getQuery())
                        .or()
                        .like(ApprovalApplication::getApprovalComment, query.getQuery());
            });
        }

        // 添加状态查询条件
        if (StringUtils.isNotBlank(query.getStatus())) {
            wrapper.eq(ApprovalApplication::getStatus, query.getStatus());
        }else{
            wrapper.in(ApprovalApplication::getStatus, Arrays.asList("0", "2", "3"));
        }

        // 添加时间范围查询条件
//        if (applyHistoryDTO.getStartDated() != null && applyHistoryDTO.getEndDated() != null) {
//            wrapper.between(ApprovalApplication::getCreatedAt,
//                    applyHistoryDTO.getStartDated(),
//                    applyHistoryDTO.getEndDated());
//        }
        wrapper.orderByDesc(ApprovalApplication::getCreatedAt);

        // 执行分页查询

        return approvalApplicationMapper.selectPage(page, wrapper);
    }

    /**
     * 月度统计
     * @param startOfMonth 月初
     * @param endOfMonth 月末
     * @return 统计结果
     */
    @Override
    public Result<StatsSnapshotVo> StatsSnapshot(LocalDateTime startOfMonth, LocalDateTime endOfMonth) {
        StatsSnapshotVo statsSnapshotVo = new StatsSnapshotVo();
        // 获取当前登录用户的ID
        Long userId = StpUtil.getLoginIdAsLong();
        StringBuilder userType = new StringBuilder("ordinary_user"); // 初始化时赋予默认值
        try {
            Set<Long> roles = userRoleMapper.selectList(new LambdaQueryWrapper<UserRole>().eq(UserRole::getUserId, userId))
                    .stream().map(UserRole::getRoleId).collect(Collectors.toSet());

            if (!roles.isEmpty()) {
                roleMapper.selectList(new LambdaQueryWrapper<Role>().eq(Role::getStatus, 0).in(Role::getId, roles))
                        .stream()
                        .filter(role -> "data_audit".equals(role.getRoleCode()))
                        .findFirst()
                        .ifPresent(role -> userType.replace(0, userType.length(), role.getRoleCode()));
            }
            // 数据上屏（个）
            statsSnapshotVo.setDisplayedDataCount(cockpitMetricsTreeMapper.selectCount());

            // 已处理申请（个）
            statsSnapshotVo.setProcessedRequestsCount(approvalApplicationMapper.selectCount(
                    new LambdaQueryWrapper<ApprovalApplication>()
                            .in(ApprovalApplication::getStatus, 3, 4)
                            .eq(!userType.toString().equals("data_audit"),ApprovalApplication::getApplicant,userId)
                            .between(ApprovalApplication::getUpdatedAt, startOfMonth, endOfMonth)
            ));

            Long count = approvalApplicationMapper.selectCount(
                    new LambdaQueryWrapper<ApprovalApplication>()
                            .eq(ApprovalApplication::getStatus, 2)
                            .eq(!userType.toString().equals("data_audit"),ApprovalApplication::getApplicant,userId)
                            .between(ApprovalApplication::getCreatedAt, startOfMonth, endOfMonth)
            );

            // 待处理申请（个）
            statsSnapshotVo.setPendingProcessingCount(count);
            // 待审批申请（个）
            statsSnapshotVo.setAwaitingApprovalCount(count);
            // 已提交申请（个）
            statsSnapshotVo.setSubmittedRequestsCount(count);
        } catch (Exception e) {
            log.error("处理月度统计数据时发生异常", e);
            return Result.error("处理月度统计数据时发生异常");
        }
        return Result.success(statsSnapshotVo);
    }
}
